package meminin.model;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import meminin.utilities.dbconn.MySqlConnector;

public abstract class MySqlTrainingData implements TrainingData {

    protected MySqlConnector connector;
    protected String dbName;
    protected String tableName;

    public MySqlTrainingData(String hostName, String dbName, String tableName, String dbUser, String dbPassword) {
        connector = new MySqlConnector(hostName, dbName, dbUser, dbPassword);
        this.dbName = dbName;
        this.tableName = tableName;
    }

    public void storeRecord(DataRecord record) {
        MySqlDataRecord sqlRec = (MySqlDataRecord) record;
        connector.executeUpdate(sqlRec.getInsertQuery(dbName, tableName));
    }

    public void updateRecords(DataRecord template, DataRecord record) {
        MySqlDataRecord sqlRec = (MySqlDataRecord) template;
        System.out.println(sqlRec.getUpdateQuery(dbName, tableName, record));
        connector.executeUpdate(sqlRec.getUpdateQuery(dbName, tableName, record));
    }

    public void deleteRecords(DataRecord template) {
        MySqlDataRecord sqlRec = (MySqlDataRecord) template;
        connector.executeUpdate(sqlRec.getDeleteQuery(dbName, tableName));
    }

    public Integer getRecordsCount(DataRecord template) {
        try {
            MySqlDataRecord sqlRec = (MySqlDataRecord) template;
            ResultSet result = connector.executeRead(sqlRec.getReadQuery(dbName, tableName));
            result.last();
            return result.getRow();
        } catch (SQLException ex) {
            Logger.getLogger(MySqlTrainingData.class.getName()).log(Level.SEVERE, null, ex);
        }
        return 0;
    }

    public ArrayList<DataRecord> getRecords(DataRecord template, DataRecord emptyTemplate) {
        ArrayList<DataRecord> tempRecords = new ArrayList<DataRecord>();
        try {
            MySqlDataRecord sqlRec = (MySqlDataRecord) template;
            ResultSet result = connector.executeRead(sqlRec.getReadQuery(dbName, tableName));
            while (result.next()) {
                tempRecords.add(MySqlDataRecord.createRecord(result, emptyTemplate));
            }
        } catch (SQLException ex) {
            Logger.getLogger(MySqlTrainingData.class.getName()).log(Level.SEVERE, null, ex);
        }
        return tempRecords;
    }

    public Boolean isAllConform(DataRecord filter, Label targetLabel) {
        ArrayList<String> values = targetLabel.getValues();
        Integer totalExamplesCount = getRecordsCount(filter);
        Boolean isConform = false;
        for (String value : values) {
            DataRecord newFilter = filter.getCopy();
            newFilter.setAttributeValue(targetLabel.getDesc(), value);
            if (totalExamplesCount == getRecordsCount(newFilter)) {
                isConform = true;
                break;
            }
        }
        return isConform;
    }

    public String getMostCommonValue(DataRecord filter, Label targetLabel) {
        ArrayList<String> values = targetLabel.getValues();
        String maxValue = "";
        Integer maxCount = 0;
        for (String value : values) {
            DataRecord newFilter = filter.getCopy();
            newFilter.setAttributeValue(targetLabel.getDesc(), value);
            Integer count = getRecordsCount(newFilter);
            if (count > maxCount) {
                maxValue = value;
                maxCount = count;
            }
        }
        return maxValue;
    }

    public String getLeastCommonValue(DataRecord filter, Label targetLabel) {
        ArrayList<String> values = targetLabel.getValues();
        String minValue = "";
        Integer minCount = getRecordsCount(filter);
        for (String value : values) {
            DataRecord newFilter = filter.getCopy();
            newFilter.setAttributeValue(targetLabel.getDesc(), value);
            Integer count = getRecordsCount(newFilter);
            if (count < minCount) {
                minValue = value;
                minCount = count;
            }
        }
        return minValue;
    }
}
